import { Injectable, OnApplicationBootstrap } from '@nestjs/common'
import { InjectRepository } from '@nestjs/typeorm'
import { FindOptionsSelect, Like, Repository } from 'typeorm'
import { ENoticeType, Notice, NoticeConfig } from '@/modules/notice/entities/notice.entity'
import { EEnableStatus } from '@/shared/types/globalEnum'
import {
  CreateNoticeConfigDto,
  CreateNoticeDto,
  FindOneNoticeDto,
  ListPaginationNoticeDto,
  ListPaginationNoticeVo,
  UpdateNoticeConfigDto,
  UpdateNoticeDto,
} from './dto/notice.dto'

@Injectable()
export class NoticeService {
  constructor(
    @InjectRepository(Notice)
    private noticeRepository: Repository<Notice>,
  ) {}

  // noticeType给空的赋值为ENoticeType.LATEST
  // async onApplicationBootstrap() {
  //   const noticeList = await this.noticeRepository.find();
  //   if (noticeList.length) {
  //     noticeList.forEach((item) => {
  //       if (!item.noticeType) {
  //         item.noticeType = ENoticeType.LATEST;
  //         this.noticeRepository.save(item);
  //       }
  //     });
  //   }
  // }

  async setAllDisable() {
    await this.noticeRepository.update({ noticeIsTop: EEnableStatus.ENABLED }, { noticeIsTop: EEnableStatus.DISABLED })
  }

  create(createData: CreateNoticeDto) {
    return this.noticeRepository.save(createData)
  }

  async findOne(data: FindOneNoticeDto) {
    return await this.noticeRepository.findOneBy(data)
  }

  // 将置顶数据放在最上面
  async findPage(query: ListPaginationNoticeDto): Promise<ListPaginationNoticeVo> {
    // 置顶公告受分类过滤，不满足“置顶在所有分类之上”的需求
    // const { pageNo = 1, pageSize = 10, ...rest } = query;
    // const [list, total] = await this.noticeRepository.findAndCount({
    //   where: {
    //     ...rest,
    //     ...(rest.noticeTitle && { noticeTitle: Like(`%${rest.noticeTitle}%`) }),
    //   },
    //   order: {
    //     noticeIsTop: 'DESC',
    //     updatedAt: 'DESC',
    //   },
    //   skip: (pageNo - 1) * pageSize,
    //   take: pageSize,
    // });

    const { pageNo = 1, pageSize = 10, noticeType, ...rest } = query
    const selectFields: FindOptionsSelect<Notice> = {
      noticeId: true,
      noticeTitle: true,
      noticeIsTop: true,
      noticeType: true,
      noticeShowTime: true,
      noticeTitleColor: true,
      noticeBackgroundColor: true,
      updatedAt: true,
      createdAt: true,
    }
    // 1. 查询置顶公告
    const topNotices = await this.noticeRepository.find({
      select: selectFields,
      where: {
        noticeIsTop: EEnableStatus.ENABLED,
        ...(rest.noticeTitle && { noticeTitle: Like(`%${rest.noticeTitle}%`) }),
      },
      order: { createdAt: 'DESC' }, // 置顶内部按更新时间排序
    })

    // 2. 查询非置顶公告（受分类过滤）
    const [list, total] = await this.noticeRepository.findAndCount({
      select: selectFields,
      where: {
        noticeIsTop: EEnableStatus.DISABLED,
        ...(noticeType && noticeType !== ENoticeType.LATEST && { noticeType }),
        ...(rest.noticeTitle && { noticeTitle: Like(`%${rest.noticeTitle}%`) }),
      },
      order: { createdAt: 'DESC' },
      skip: (pageNo - 1) * pageSize,
      take: pageSize,
    })

    // 3. 合并
    const finalList = [...topNotices, ...list]
    const mergeTotal = topNotices.length + total

    return {
      total: mergeTotal,
      list: finalList,
    }
  }

  async update(homeId: number, updateData: UpdateNoticeDto) {
    return this.noticeRepository.update(homeId, {
      ...updateData,
      noticeId: undefined,
    })
  }

  remove(noticeId: number) {
    return this.noticeRepository.delete(noticeId)
  }
}

@Injectable()
export class NoticeConfigService implements OnApplicationBootstrap {
  constructor(
    @InjectRepository(NoticeConfig)
    private noticeConfigRepository: Repository<NoticeConfig>,
  ) {}

  async onApplicationBootstrap() {
    const exists = await this.findOne()
    if (!exists) {
      await this.create({})
      console.log('文章配置已初始化')
    }
  }

  create(createData: CreateNoticeConfigDto) {
    return this.noticeConfigRepository.save(createData)
  }

  async findOne() {
    const [config] = await this.noticeConfigRepository.find({
      take: 1,
    })
    return config
  }

  async update(noticeConfigId: number, updateData: UpdateNoticeConfigDto) {
    return this.noticeConfigRepository.update(noticeConfigId, {
      ...updateData,
      noticeConfigId: undefined,
    })
  }
}
